<?php

class Lastfm {

    private $api_key = 'changeme';
    private $cache_lifetime = 7200; // 2 hours
    private $cache_table = 'sys.lastfm_cache';

    protected $dbo = NULL;

    public function __construct() {

        $this->dbo  = &DBO::getInstance();

    }

    private function _cache_result($method, $params, $result) {
        $stored_params = '';

        foreach($params as $key => $value)
            $stored_params .= sprintf('&%s=%s', $key, $value);

        $res = $this->dbo->query("SELECT sys.lastfm_cache_result(?,?,?)",
            array(
                DBString::create($method),
                DBString::create($stored_params),
                DBString::create($result)
            ));

        throwOnError($res);

        return true;
    }

    private function _get_cached_result($method, $params) {

        $stored_params = '';

        foreach($params as $key => $value)
            $stored_params .= sprintf('&%s=%s', $key, $value);

        $res = $this->dbo->getRow("SELECT 
            result, date_part('epoch', time) as time
            FROM $this->cache_table
            WHERE method = ? AND params = ?",
            array(
                DBString::create($method),
                DBString::create($stored_params)
            ), DB_FETCHMODE_ASSOC);

        throwOnError($res);

        return $res;
    }

    private function _get_result($method, $params) {

        $query = sprintf('http://ws.audioscrobbler.com/2.0/?method=%s&api_key=%s',
            $method, $this->api_key);

        foreach($params as $key => $value)
            $query .= sprintf('&%s=%s', $key, $value);

        $xml = new SimpleXMLElement($query, null, true);

        return $xml;
    }

    public function api_query($method, $params) {

        $cached_result = $this->_get_cached_result($method, $params);

        if(empty($cached_result)) {

            $xml = $this->_get_result($method, $params);

            $this->_cache_result($method, $params, $xml->asXML());

        } else {

            if($cached_result['time'] < (time() - $this->cache_lifetime)) {

                $xml = $this->_get_result($method, $params);

                $this->_cache_result($method, $params, $xml->asXML());

            } else {

                $xml = new SimpleXMLElement($cached_result['result']);
            }
        }

        return $xml;
    }
    
    public function updateArtistTags($artist_id, $tag_count = 7) {

        $artist = Artist::getById($artist_id);

        if(! ($artist instanceof Artist))
            throw new Exception(_('Failed to load artist.'));

        $xml = $this->api_query('artist.gettoptags', array('artist' => urlencode($artist->name)));

        if(empty($xml))
            throw new Exception(_('Failed to fetch Last.fm data.'));

        if($xml->attributes()->status != 'ok')
            throw new Exception(_('Failed to load artist tags.'));

        try {

            for($i = 0; $i < $tag_count; $i++)
                $tags[] = $xml->toptags->tag[$i]->name;

        } catch (Exception $e) {

            // do nothing
        }

        //var_dump($tags);
        foreach($tags as $tagname) {

            if(!empty($tagname))
                $artist->linkWithTag($tagname);
        }

        return $tags;
    }

    public function updateArtistPicture($artist_id) {

        $artist = Artist::getById($artist_id);

        if(! ($artist instanceof Artist))
            throw new Exception(_('Failed to load artist.'));

        $xml = $this->api_query('artist.getimages',
            array(
                'artist' => urlencode($artist->name),
                'page' => 1,
                'limit' => 1,
                'order' => 'popularity'
            ));

        if(empty($xml))
            throw new Exception(_('Failed to fetch Last.fm data.'));

        if($xml->attributes()->status != 'ok')
            throw new Exception(_('Failed to load artist tags.'));

        foreach($xml->images->image[0]->sizes->size as $xml_size) {
            if($xml_size->attributes()->name == 'original') {
                //$artist->picture_path = $xml_size;
                //$artist->save();
                $artist->uploadPictureFromUrl($xml_size);
                break;
            }
        }
        return $xml_size;
    }

    public function getUserTopArtists($user_name, $period = 'overall') {

        $xml = $this->api_query('user.gettopartists',
            array(
                'user' => urlencode($user_name),
                'period' => $period
        ));

        if(empty($xml))
            throw new Exception(_('Failed to fetch Last.fm data.'));

        if($xml->attributes()->status != 'ok')
            throw new Exception(_('Failed to get user top artists.'));

        $result = array();

        foreach($xml->topartists->artist as $xml_artist) {
            $result[] = $xml_artist->name;
        }

        return $result;

    }

}